package com.ruoyi.system.service.impl;

import java.io.*;
import java.util.List;
import java.util.UUID;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.exception.file.FileException;
import com.ruoyi.common.utils.file.FileUtil;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.file.PdfToImageUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysFileMapper;
import com.ruoyi.system.domain.SysFile;
import com.ruoyi.system.service.ISysFileService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;

/**
 * 附件Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-09-04
 */
@Service
@ConditionalOnProperty(value = "file.upload-type", havingValue = "local", matchIfMissing = true)
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService
{
    public static String BASE_DIR = "/upload/";
    @Value("${file.thumbnail.enable: false}")
    private boolean thumbnailEnable;
    @Value("${ruoyi.profile}")
    private String uploadPath;

    @Override
    public void download(String filePath, String fileName, Boolean delete, HttpServletResponse response) {
        FileUtil.downLoadFile(uploadPath + File.separator + filePath.replace(BASE_DIR, ""), true, response);
    }

    @Override
    public byte[] getFile(String filePath, Boolean delete) {
        return returnFile(filePath, delete);
    }

    @Override
    public byte[] returnFile(String filePath, Boolean delete) {
        return FileUtil.getFile(uploadPath + File.separator + filePath.replace(BASE_DIR, ""), true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFile upload(MultipartFile file) {
        if (null == file) {
            throw new FileException("文件不能为空！");
        }
        final String attachSuffix = FileUtil.getFileExtension(file.getOriginalFilename());
        try {
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = uuid + "." + attachSuffix;
            FileUtil.saveFile(file, uploadPath, fileName);
            return saveFileEntity(attachSuffix, uuid, fileName, file.getSize(), file.getOriginalFilename(), thumbnailEnable);
        } catch (Exception e) {
            e.printStackTrace();
            throw new FileException("文件上传失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SysFile> upload(MultipartFile[] file) {
        if (null == file) {
            throw new FileException("文件不能为空！");
        }
        List<SysFile> files = Lists.newArrayList();
        for (MultipartFile multipartFile : file) {
            final String attachSuffix = FileUtil.getFileExtension(multipartFile.getOriginalFilename());
            try {
                String uuid = UUID.randomUUID().toString().replace("-", "");
                String fileName = uuid + "." + attachSuffix;
                FileUtil.saveFile(multipartFile, uploadPath, fileName);
                files.add(saveFileEntity(attachSuffix, uuid, fileName, multipartFile.getSize(), multipartFile.getOriginalFilename(), thumbnailEnable));
            } catch (Exception e) {
                e.printStackTrace();
                throw new FileException("文件上传失败");
            }
        }
        return files;
    }

    @Override
    public SysFile uploadImg(MultipartFile file, int width, int height) {
        try {
            //压缩文件
            InputStream imgStream = file.getInputStream();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Thumbnails.of(imgStream).size(width, height).toOutputStream(outputStream);
            FileUtil.saveFile(outputStream.toByteArray(), uploadPath, file.getOriginalFilename());
            SysFile fileEntity = new SysFile();
            fileEntity.setFileSize(file.getSize());
            fileEntity.setType(FileUtil.getFileExtension(file.getOriginalFilename()));
            fileEntity.setSource(SysFile.SOURCE_SYSTEM);
            fileEntity.setFileName(file.getOriginalFilename());
            fileEntity.setPath(BASE_DIR + File.separator + file.getOriginalFilename());
            super.save(fileEntity);
            return fileEntity;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public SysFile upload(File file) {
        if (null == file) {
            throw new FileException("文件为空！");
        }
        final String attachSuffix = FileUtil.getFileExtension(file.getName());
        try {
            String uuid = UUID.randomUUID().toString().replace("-", "");
            FileInputStream fileInputStream = new FileInputStream(file);
            FileUtil.saveFile(fileInputStream, uploadPath, file.getName());
            return saveFileEntity(attachSuffix, uuid, file.getName(), file.length(), file.getName(), thumbnailEnable);
        } catch (IOException e) {
            e.printStackTrace();
            throw new FileException("文件上传失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long fileId) {
        SysFile fileEntity = getById(fileId);
        if (fileEntity != null) {
            FileUtil.deleteFile(uploadPath + File.separator + fileEntity.getPath().replace(BASE_DIR, ""));
            baseMapper.deleteById(fileId);
        }
    }

    @Override
    public void downloadPDF(Long fileId, String pdfFontPath, String markStr, HttpServletResponse response) {
        SysFile sysFile = getById(fileId);
        String filePath = uploadPath + File.separator + sysFile.getPath().replace(BASE_DIR, "");
        File file = new File(filePath);
        try {
            String newFilePath = PdfToImageUtil.watermark(file, pdfFontPath, markStr);
            FileUtil.downLoadFile(newFilePath, true, response);
            FileUtil.deleteFile(newFilePath);
        } catch (Exception e) {
            e.printStackTrace();
            throw new FileException("PDF下载失败！");
        }
    }

    @Override
    public SysFile upload(byte[] bytes, String oriFileName, String fileExtension) {
        try {
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = uuid + "." + fileExtension;
            FileUtil.saveFile(bytes, uploadPath, fileName);
            return saveFileEntity(fileExtension, uuid, fileName, (long) bytes.length, oriFileName, thumbnailEnable);
        } catch (Exception e) {
            e.printStackTrace();
            throw new FileException("文件上传失败");
        }
    }

    private SysFile saveFileEntity(String attachSuffix, String uuid, String fileName, Long fileSize, String orgName, Boolean isThumbnail) {
        String thumbnail = null;
        if (Lists.newArrayList(MimeTypeUtils.IMAGE_EXTENSION).contains(attachSuffix) && isThumbnail) {
            thumbnail = uuid + "_150x300.jpg";
            String filePath = uploadPath + File.separator + fileName;
            String thumbnailPath = uploadPath + File.separator + thumbnail;
            try {
                Thumbnails.of(filePath).size(150, 300).toFile(thumbnailPath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        SysFile fileEntity = new SysFile();
        fileEntity.setFileSize(fileSize);
        fileEntity.setThumbnail(thumbnail);
        fileEntity.setType(attachSuffix);
        fileEntity.setSource(SysFile.SOURCE_SYSTEM);
        fileEntity.setFileName(orgName);
        fileEntity.setPath(BASE_DIR + File.separator + fileName);
        super.save(fileEntity);
        return fileEntity;
    }
}
